package io.seata.storage.service.impl;

import io.seata.common.dto.StorageDTO;
import io.seata.common.enums.RspStatusEnum;
import io.seata.common.exception.DefaultException;
import io.seata.common.response.ObjectResponse;
import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.storage.entity.Storage;
import io.seata.storage.entity.StorageFreeze;
import io.seata.storage.mapper.StorageFreezeMapper;
import io.seata.storage.mapper.StorageMapper;
import io.seata.storage.service.StorageTCCService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

@Service
@Slf4j
public class StorageTCCServiceImpl implements StorageTCCService {

    @Resource
    private StorageMapper storageMapper;

    @Resource
    private StorageFreezeMapper storageFreezeMapper;

    @Override
    @Transactional
    public ObjectResponse deduct(StorageDTO storageDTO) {

        ObjectResponse objectResponse = new ObjectResponse();
        // 0.获取事务id
        String xid = RootContext.getXID();
        //判断是否业务悬挂
        if(storageFreezeMapper.selectById(xid) != null) {
            log.error("业务悬挂");
            throw new DefaultException(RspStatusEnum.EXCEPTION);
        }

        // 1.扣减库存
        Storage storage = new Storage();
        storage.setCommodityCode(storageDTO.getCommodityCode());
        storage.setCount(storageDTO.getCount());
        storageMapper.deduct(storage);
        // 2.记录冻结库存，事务状态
        StorageFreeze freeze = new StorageFreeze();
        freeze.setXid(xid);
        freeze.setCommodityCode(storageDTO.getCommodityCode());
        freeze.setFreezeCount(storageDTO.getCount());
        freeze.setState(StorageFreeze.State.TRY);
        storageFreezeMapper.insert(freeze);

        objectResponse.setStatus(RspStatusEnum.SUCCESS.getCode());
        objectResponse.setMessage(RspStatusEnum.SUCCESS.getMessage());
        return objectResponse;
    }

    @Override
    public boolean confirm(BusinessActionContext ctx) {
        // 1.获取事务id
        String xid = ctx.getXid();
        // 2.根据id删除冻结记录
        int count = storageFreezeMapper.deleteById(xid);
        return count == 1;
    }

    @Override
    public boolean cancel(BusinessActionContext ctx) {
        // 0.查询冻结记录
        String xid = ctx.getXid();
        StorageFreeze freeze = storageFreezeMapper.selectById(xid);
        //判断是否为空回滚，空回滚不执行业务
        if (freeze != null && freeze.getState().equals(StorageFreeze.State.TRY)) {
            // 1.恢复库存
            Storage storage = new Storage();
            storage.setCommodityCode(freeze.getCommodityCode());
            storage.setCount(freeze.getFreezeCount());
            storageMapper.refund(storage);
            // 2.将冻结库存清零，状态改为CANCEL
            freeze.setFreezeCount(0);
            freeze.setState(StorageFreeze.State.CANCEL);
            int count = storageFreezeMapper.updateById(freeze);
            return count == 1;
        }
        log.error("空回滚");
        return true;
    }
}
